package cn.group01.git.aop;

import cn.group01.git.annotations.LogOperation;
import cn.group01.git.entity.LogInfo;
import cn.group01.git.entity.User;
import cn.group01.git.service.LogService;
import cn.group01.git.utils.IpUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;

@Component
@Aspect
public class LogAspect {

    @Autowired
    private LogService logService;

    @Pointcut("@annotation(cn.group01.git.annotations.LogOperation)")
    public void pointCut(){}

    @Around("pointCut()")
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
        Object proceed = null;
        try {
            proceed = proceedingJoinPoint.proceed();
            // 获取日志信息 username ip url model description args。

            // args
            Object[] args = proceedingJoinPoint.getArgs(); // 获取Object[]类型的参数args
            String strArgs = StringUtils.arrayToCommaDelimitedString(args);// 将Object[]类型的参数args转换成用逗号连接的String类型参数

            // model description ==> 通过Method对象获取
            MethodSignature signature = (MethodSignature)proceedingJoinPoint.getSignature();// 将签名强转成方法签名
            Method method = signature.getMethod(); // 用方法签名获取方法对象

            LogOperation annotation = method.getAnnotation(LogOperation.class); // 获取注解
            String description = annotation.description().getDescription(); // 获取注解属性description 吗枚举类型 所以需要get一下
            String model = annotation.model(); // String类型 直接拿

            //  username ip url ==> 用request对象
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();

            HttpSession session = request.getSession();
            User user = (User)session.getAttribute("user");
            String username = user.getUsername();
            String uri = request.getRequestURI();

            String ip = IpUtil.getIp(request);

            LogInfo logInfo = new LogInfo();
            logInfo.setParams(strArgs);
            logInfo.setModel(model);
            logInfo.setDescription(description);
            logInfo.setUsername(username);
            logInfo.setIp(ip);
            logInfo.setCreateTime(new Date());
            logInfo.setUrl(uri);
            // 将日志信息写入数据库
            logService.addLog(logInfo);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        return proceed;
    }
}
